package com.xianggu.Collection.queue;

import java.util.Iterator;
import java.util.Spliterator;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;

/**
 * @author chengjy
 * @date 2025/3/31
 */
public class BlockQueue<T> implements Queue<T>, Iterable<T> {
    // 链表实现
    private Node first;
    private Node last;
    private volatile int size;
    // 队列容量
    private int capacity;

    private volatile AtomicInteger lockCount = new AtomicInteger(0);
    private ReentrantLock lock = new ReentrantLock();
    // 队列满的条件
    private Condition notFull;
    // 队列空的条件
    private Condition notEmpty;

    public BlockQueue(int capacity) {
        this.capacity = capacity;
        notFull = lock.newCondition();
        notEmpty = lock.newCondition();
    }

    @Override
    public void enqueue(T item) {
        lock.lock();
        try {
            while (this.size == capacity) {
                System.out.println(Thread.currentThread().getName() + " 队列已满，生产者等待消费者消费");
                notFull.await();
            }// 加入等待队列，等消费者唤醒

            // new一个节点，尾节点指向新元素
            Node currentNode = new Node(item);
            if (last == null || isEmpty()) {
                last = currentNode;
                first = last;
            } else {
                last.next = currentNode;
                last = currentNode;
            }
            size++;

            // 唤醒等待的消费者
            notEmpty.signal();

        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            lock.unlock();
        }
    }

    @Override
    public T dequeue() {
        lock.lock();

        try {
            while (true) {
                if (this.size == 0) {
                    System.out.println(Thread.currentThread().getName() + " 队列已空，消费者等待生产者生产");
                    notEmpty.await();// 阻塞，等待消费者唤醒
                }
                // 从头结点开始出队
                if (first != null) {
                    Node oldNode = first;
                    first = oldNode.next;
                    size--;
                    notFull.signal();// 唤醒生产者

                    return (T) oldNode.item;
                }
            }

        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            lock.unlock();
        }


    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * Returns an iterator over elements of type {@code T}.
     *
     * @return an Iterator.
     */
    @Override
    public Iterator<T> iterator() {
        return new BlockQueueIterator<T>(first);
    }


    class BlockQueueIterator<T> implements Iterator<T> {

        private Node current;

        public BlockQueueIterator(Node current) {
            this.current = current;
        }

        @Override
        public boolean hasNext() {
            return current != null;
        }

        @Override
        public T next() {
            Node first = current;
            current = first.next;
            return (T) first.item;
        }
    }
}
